js-11 事件对象

一、事件

事件函数:事件要调用的函数;

事件处理函数:事件触发时要执行的函数;

事件对象:事件发生时,与这个事件有关的信息保存的一个对象;

当一个事件发生时,将有关信息保存在事件函数的内置全局对象event当中,可以直接使用,包括事件类型,操作对象,鼠标位置;

常用的内置对象:

  • type:获取事件类型;

  • target(srcElement(ie8-)):获取触发事件的对象;

  • clientX/Y:鼠标到文档可视区的坐标点;

  • offsetX/Y:当前位置距离上一个定位元素的距离

  • screenX/Y:当前位置距离屏幕的坐标点

  • pageX/Y,鼠标到文档的距离,包括滚动的地方;ie8以下没有;

  • e.button 0是鼠标左键,1是滚动按下 2是鼠标右键

IE/谷歌:使用事件函数内的内置对象;

标准浏览器:使用事件函数的第一个参数形参;

做兼容:

//如果不做ie8兼容,就可以不用写
div.onclick  = function(ev){
    var ev = ev || window.event;
}

二、事件绑定

  1. 定义:在一个元素上绑定多个事件,不会覆盖,都会执行;
  2. obj.addEventListener("click",fn,false); 标准,true(捕获),false(冒泡);this指向自己;

事件不需要加on,事件处理函数,布尔值); 缺点:不兼容IE;

  1. 元素.attachEvent(事件(要加on),事件处理函数);只有冒泡;倒序执行;IE8及以下;非标准;this指向window;

做兼容:

function setEvent(obj,even,fn){ //元素,事件,事件处理函数;
if(obj.attachEvent){
    obj.attachEvent("on" + even,fn);
}else{
    obj.addEventListener(even,fn,true);
    }
}

标准浏览器的事件绑定和 ie 浏览器的事件绑定的区别:

(1)ie 没有捕获,标准有捕获

(2)ie 的事件名称前面有 on,标准没有

(3)标准的 ie 会根据事件的顺序正序执行,非 ie 标准逆序,标准正序

(4)ie 的 this 是 window,标准的是触发这个事件的对象

(4)标准浏览器的事件绑定和 ie 浏览器的事件绑定是不共存的,因此我们需要进行一个兼容的操作,一般情况下,如果是两个方法的兼容,那么就拿出其中一个方法,在各个浏览器中查看获取的值,标准浏览器和 ie 浏览器会得到不一样的结果。

三、取消事件绑定

取消事件绑定最好明确函数的名字,不然会有很多不确定的因素;

  1. 普通的:元素.onclick = null;
  2. addEventListener事件函数:removeEventListener("事件",事件处理函数);
  3. attachEvent事件函数:detachEvent("事件",事件处理函数);

四、事件流

捕获: 当父元素和子元素都绑定了事件,先触发父元素,再触发子元素,从外到内;

冒泡: 先触发子元素再触发父元素,从内到外;

事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即 DOM 事件流。

DOM 事件流会有 3 个阶段:

事件捕获阶段:事件的传播是从最不特定的事件目标到最特定的事件目标。即从 DOM树的根到叶子。

确定目标阶段:通过捕获确定具体触发事件的元素

事件冒泡阶段:事件的传播是从最特定的事件目标到最不特定的事件目标。即从 DOM树的叶子到根。

五、阻止冒泡事件(掌握)

问题:子元素设置事件,再给其父元素设置事件,当触发子元素事件的时候,其父元素的事件也触发了,子元素监听到触发事件,所有包含事件的父元素都会触发;

阻止:

event.stopPropagation();IE8以下不兼容; Propagation 传播传递

event.cancelBubble=true;IE8以下兼容; Bubble冒泡,cancel取消;

做兼容:

event.stopPropagation ? event.stopPropagation() : window.event.cancelBubble = true;

注意:不是所有的事件都能冒泡,blurfocusloadunload不能冒泡;

六、事件委托

  1. 将子元素要做的事情委托给父元素;event.target;
  2. 使用场景:子元素很多,事件相同的使用,后添加的相同元素会有相同的脚本;
  3. 原理:事件委托是利用事件冒泡原理来实现的,因为点击子元素会冒泡到父元素,那么给父元素做点击事件,里面的元素做点击事件时,都会冒泡到父元素身上,这就是事件委托,委托它们的父级代为执行事件;
  4. 事件委托实现:将事件添加到父元素上,当事件发生时,父元素会找到对应触发事件的子元素去处理,后期添加的子元素,依然有这个事件。

事件源不兼容IE8-,IE8支持:event.srcElement

事件源兼容:

var target = ev.target || ev.srcElement;

七、取消事件默认行为

  1. return false;对事件绑定设置的不起作用,也可以直接使用以下的两种;
  2. 事件绑定的阻止默认行为:event.preventDefault()
  3. IE事件绑定:event.returnValue = false

总结:

事件绑定取消事件绑定阻止事件冒泡事件委托取消默认行为
通常obj.事件=函数onclick = nullreturn false
标准浏览器addEventListenerremoveEventListenerstopPropagationevent.targetevent.preventDefault()
非标准浏览器attachEventdetachEventcancelBubbleevent.srcElementevent.returnValue = false;

八、键盘事件

  1. onkeydown;按下;不区分大小写
  2. onkeyup;抬起;
  3. onkeypress;比onkeydown后触发,区分大小写,只能包含数字和字母,大小写是反过来的;不能获取到功能键,如箭头;

键盘值: event.key 获得按下的键;

event.keyCode 获得按下的键码值,字母为大写的Unicode码;

event.shiftKey;是否按下shift键,返回布尔值;

event.ctrlKey;是否按下ctrl键;

event.altKey;是否按下alt键;

  • 扩展

compositionstart 中文输入法输入开始时触发。

compositionend 中文输入法输入结束时触发。

九、鼠标滚轮事件:

元素.onmousewheel 滚动的时候触发;

event.wheelDelta:120向上滚动;-120向下滚动;

火狐浏览器需要通过绑定事件获取:

div.addEventListener("DOMMouseScroll",事件处理函数)

event.detail:-3向上滚动,3向下滚动;

十、customEvent事件

自定义事件,就跟vue里面的on跟emit一样

监听自定义事件

window.addEventListener('follow',event=>{
    console.log(event.detail)  // {name:'前端'}
})

派发自定义事件

window.dispatchEvent(new CustomEvent('follow',{
    detail:{
        name:'前端'
    }
}))

例子:

var div = document.createElement('div')
div.click = function(){
    console.log('被点击了111111')
}
var click = new Event('click')
div.dispatchEvent(click)

十一、监控事件

  • 使用 monitorEvents 侦听特定类型的事件。
  • 使用 unmonitorEvents 停止侦听。
  • 使用 getEventListeners 获取 DOM 元素的所有事件
  • 使用“Event Listeners Inspector”面板获取有关事件侦听器的信息。

获取元素绑定的事件对象:getEventListeners(元素); 需要在控制台打印:

监控元素上的事件命令: monitorEventsunmonitorEvents

monitorEvents(元素,[可选的事件名字])

monitorEvents(document,'click')

十二、try catch

用来捕获出错的代码,try..catch只能捕获同步代码,不能捕获异步代码的错误;

如果出错了,则不能执行下面的步骤,因此可以使用try来捕获错误

try{
    //可能成功的事件
} catch (e) {
    //捕获错误
} finally {
    // 无论成功于否都会执行
}

高频面试题

● 事件、IE 与火狐的事件机制有什么区别?

● 如何阻止冒泡?

● 事件绑定和普通事件有什么区别。

● 如何用原生 js 给元素绑定两个 click 事件?

● 解释一下事件流?

● 事件委托是什么。

● 给 10000 个 li 添加点击事件。